package samples.zipcodes;


import java.util.ArrayList;
import java.util.List;

import org.dom4j.Element;
import org.dom4j.XPathException;

import br.cin.ufpe.in1118.middleware.distribution.message.SOAPFactory;
import br.cin.ufpe.in1118.middleware.distribution.message.SOAPFaultException;
import br.cin.ufpe.in1118.middleware.distribution.services.util.MiddlewareUtil;
import br.cin.ufpe.in1118.middleware.exceptions.RemoteException;

public final class ZipCodes_SF extends SOAPFactory {

	@Override
	public Object fromSOAP(String operation, String soapMessage) throws RemoteException {
		Element rootElement = null;
		try {
			rootElement = createRootElement(soapMessage);
			
			if (operation.equals("ZipCodeToLatitudeLogitude")) {
				Element response = (Element) rootElement.selectSingleNode("//Coordinates");
				Coordinates coords = new Coordinates();
				if (response != null) {
					coords.setLatitude(Double.parseDouble(response.element("latitude").getText()));
					coords.setLongitude(Double.parseDouble(response.element("longitude").getText()));
				}
				return coords;
			} else if (operation.equals("ZipCodeToDetails")) {
				Element response = (Element) rootElement.selectSingleNode("//Details");
				ZipCodeDetails details = new ZipCodeDetails();
				if (response != null) {
					details.getCoordinates().setLatitude(Double.parseDouble(response.element("latitude").getText()));
					details.getCoordinates().setLongitude(Double.parseDouble(response.element("longitude").getText()));
					details.setCity(response.element("city").getText());
					details.setState(response.element("state").getText());
					details.setCounty(response.element("county").getText());
					details.setAddressType(response.element("addresstype").getText());
				}
				return details;
			} else if (operation.equals("ZipCodesFromCityState")) {
				List<?> nodes = rootElement.selectNodes("//ZipCodes");
				List<String> zipCodes = new ArrayList<String>();
				for (Object obj : nodes) {
					if (obj instanceof Element) {
						Element response = ((Element) obj).element("zipcode");
						if (response != null) {
							zipCodes.add(response.getText());
						}
					}
				}
				return zipCodes;
			} 
		} catch (XPathException e) {
			Element elem = (Element) rootElement.selectSingleNode("//faultstring");
			throw new RemoteException(new SOAPFaultException(elem.getText()));
		} catch (Exception e) {
			MiddlewareUtil.encapsulateException(e);
		}
		return null;
	}

	@Override
	public String toSOAP(String operation, Object... parameters) {
		String body = null;
		
		if (operation.equals("ZipCodeToLatitudeLogitude")) {
			body = String.format("<ZipCodeToLatitudeLogitude" +
					" xmlns=\"http://www.jasongaylord.com/webservices/zipcodes\">" +
					"<ZipCode>%s</ZipCode>" +
					"</ZipCodeToLatitudeLogitude>", parameters[0]);
		} else if (operation.equals("ZipCodeToDetails")) {
			body = String.format("<ZipCodeToDetails" +
			" xmlns=\"http://www.jasongaylord.com/webservices/zipcodes\">" +
			"<ZipCode>%s</ZipCode>" +
			"</ZipCodeToDetails>", parameters[0]);
		} else if (operation.equals("ZipCodesFromCityState")) {
			body = String.format("<ZipCodesFromCityState" +
					" xmlns=\"http://www.jasongaylord.com/webservices/zipcodes\">" +
					"<City>%s</City><State>%s</State>" +
					"</ZipCodesFromCityState>", parameters[0], parameters[1]);
		} 
		
		return String.format("%s\n%s\n%s\n%s\n%s\n%s\n",
				TEMPLATE_XML_DECLARATION,
				TEMPLATE_HEADER_ENV,
				TEMPLATE_HEADER_BODY,
				body,
				TEMPLATE_TAIL_BODY,
				TEMPLATE_TAIL_ENV);
	}
	
	@Override
	public String getOperationName(String operation) {
		return "http://www.jasongaylord.com/webservices/zipcodes/" + (operation);
	}

}
